package com.calculation.demo02;

import java.math.BigInteger;

public class Test {
    public static void main(String[] args) {
        System.out.println("BigInteger学习");
        /**
         * 为什么？当我们计算的数值超过了 Long整数类型范围，
         * 是什么？可以表示任意大小的整数，用于超大的整数运算
         * 怎么用？调用对应的api接口
         */
        Long l1 = 12345678999L;
        Long l2 = 12345678999000000L;
        System.out.println(l1 * l2); // -8687561832906512832 显示错误了，超出范围了
        /**
         * 和 long型整数运算比，BigInteger不会有范围限制，但缺点是速度比较慢。
         * 大数值：使用 BigInteger 运算
         */

        /**
         * ————————————————
         * 2、构造器描述
         * BigInteger(String)   创建一个具有参数所指定以字符串表示的数值的对象。推荐使用
         * ————————————————
         */
        BigInteger bg1 = new BigInteger("12345678999");
        BigInteger bg2 = new BigInteger("12345678999000001");
        System.out.println(bg1.multiply(bg2)); // 输出 152415789946349642001000000 表示正常 ，解决了超出了Long类型的范围

        /**
         * 3、基础运算的方法 加、减、乘、除
         * add(); 加法
         * subtract(); 减法
         * multiply(); 乘法
         * divide(); 除法
         * remainder();取余
         * ...
         */
        BigInteger bg_add =  bg1.add(bg2);
        System.out.println(bg_add); // 加法
        BigInteger bg_sub = bg2.subtract(bg1);
        System.out.println(bg_sub); // 减法
        BigInteger bg_mul = bg1.multiply(bg2);
        System.out.println(bg_mul); // 乘法
        BigInteger bg_div = bg2.divide(bg1);
        System.out.println(bg_div); // 除法
        /**
         * BigInteger 和 基本类型转换
         * BigInteger和Integer、Long一样，也是不可变类，并且也继承自Number类
         * Number定义了转换为基本类型的几个方法：
         * 转换为byte：byteValue()
         * 转换为short：shortValue()
         * 转换为int：intValue()
         * 转换为long：longValue()
         * 转换为float：floatValue()
         * 转换为double：doubleValue()
         */
        BigInteger bg_num = new BigInteger("1000");
        BigInteger bg_compare = new BigInteger("1000");
        int num = bg_num.intValue(); // 转型 int类型
        System.out.println(num);// 1000
        double d_num = bg_num.doubleValue();
        System.out.println(d_num); // 1000.0
        Long l_num = bg_num.longValue();
        System.out.println(l_num); // 1000
        /**
         * 如果BigInteger表示的范围超过了基本类型的范围，转换时将丢失高位信息，即结果不一定是准确的。
         * 如果需要准确地转换成基本类型，可以使用intValueExact()、longValueExact()等方法，
         * 在转换时如果超出基本类型的数值范围，将直接抛出ArithmeticException异常。
         *
         * 确保精度问题：使用下面转为基本类型
         * 转换为byte：byteValueExact()
         * 转换为short：shortValueExact()
         * 转换为int：intValueExact()
         * 转换为long：longValueExact()
         * 转换为float：floatValueExact()
         * 转换为double：doubleValueExact()
         */
        // 例如：
        BigInteger i = new BigInteger("9992345678900990000");
        Long max_l_num = i.longValue(); // 失去最高位 变为负数  超出 Long 范围
        System.out.println(max_l_num); // -8454398394808561616
        /**
         * 报错 java.lang.ArithmeticException: BigInteger out of long range
         * 报错了 超出基本Long类型的范围
         */
        // System.out.println(i.longValueExact());

        boolean equals = bg_num.equals(bg_compare);
        int cmp = bg_num.compareTo(bg_compare);
        System.out.println(equals);
        System.out.println(cmp);
    }
}
